from sqlalchemy import func
from sqlalchemy.orm import Session

from app.database import engine
from app.models import Posts, Likes, Comments
from app.schemas.circle import CirclePostsSM, CircleLikesSM, CircleCommentsSM, CircleList, Item
from app.services.friends import FriendsServices
from app.services.orm import pagination


class CircleServices:
    @staticmethod
    def posts_list(page: int, page_size: int):
        return pagination(page, page_size, Posts)

    @staticmethod
    def circle_friends(user_id: int, page, page_size):
        offset = (page - 1) * page_size
        friends_ids = FriendsServices.get_my_friends_ids(user_id)
        with Session(engine) as session:
            total = session.query(func.count()).œ(Posts).filter(Posts.uid.in_(friends_ids)).scalar()
            friends_circle = session.query(Posts).filter(Posts.uid.in_(friends_ids)).order_by(
                Posts.created_at.desc()).offset(offset).limit(page_size).all()
            items = [Item(**post.__dict__) for post in friends_circle]

            return CircleList(list=items, total=total)

    @staticmethod
    def circle_recommend(page, page_size):
        offset = (page - 1) * page_size
        with Session(engine) as session:
            total = session.query(func.count()).select_from(Posts).scalar()
            friends_circle = session.query(Posts).order_by(
                Posts.created_at.desc()).offset(offset).limit(page_size).all()
            items = [Item(**post.__dict__) for post in friends_circle]

            return CircleList(list=items, total=total)

    @staticmethod
    def posts_store(user_id, form: CirclePostsSM):
        with Session(engine) as session:
            form.uid = user_id
            obj = Posts(**form.dict())
            session.add(obj)
            session.commit()
        return True

    @staticmethod
    def posts_destroy(posts_id: int):
        with Session(engine) as session:
            session.query(Posts).filter_by(id=posts_id).delete()
            session.commit()
        return True

    @staticmethod
    def likes_store(user_id, form: CircleLikesSM):
        with Session(engine) as session:
            try:
                form.uid = user_id
                obj = Likes(**form.dict())
                session.add(obj)
                session.commit()
            except Exception as e:
                session.rollback()
                print(e)
                return False

            obj = session.query(Posts).filter_by(id=form.post_id)
            likes_count = obj.first().likes_count
            obj.update({'likes_count': ++likes_count})
            session.commit()
        return True

    @staticmethod
    def likes_destroy(likes_id: int):
        with Session(engine) as session:
            try:
                obj = session.query(Likes).filter_by(id=likes_id)
                posts_id = obj.first().post_id
                obj.delete()
                session.commit()
            except Exception as e:
                print(e)
                session.rollback()
                return False
            obj = session.query(Posts).filter_by(id=posts_id)
            likes_count = obj.first().likes_count
            obj.update({'likes_count': --likes_count})
            session.commit()
        return True

    @staticmethod
    def comments_store(user_id, form: CircleCommentsSM):
        with Session(engine) as session:
            try:
                form.uid = user_id
                obj = Comments(**form.dict())
                session.add(obj)
                session.commit()
            except Exception as e:
                session.rollback()
                print(e)
                return False

            obj = session.query(Posts).filter_by(id=form.post_id)
            comments_count = obj.first().comments_count
            obj.update({'comments_count': ++comments_count})
            session.commit()

        return True

    @staticmethod
    def comments_destroy(comments_id: int):
        with Session(engine) as session:
            try:
                obj = session.query(Likes).filter_by(id=comments_id)
                posts_id = obj.first().post_id
                obj.delete()
                session.commit()
            except Exception as e:
                print(e)
                session.rollback()
                return False
            obj = session.query(Posts).filter_by(id=posts_id)
            comments_count = obj.first().comments_count
            obj.update({'comments_count': --comments_count})
            session.commit()

        return True
